home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Panorama
/
Panorama - Disk 28C (1988-04-27)(Pacific North-West Amigas Club)[WB].zip
/
Panorama - Disk 28C (1988-04-27)(Pacific North-West Amigas Club)[WB].adf
/
ModulaII
/
Dhrystone
/
Dhry.Mod
Wrap
Text File
|
1988-03-15
|
16KB
|
493 lines
MODULE Dhrystone;
(*---------------------------------------------------------------------------
"DHRYSTONE" Benchmark Program
-----------------------------
Version: Commodore Amiga Benchmark Modula-2. Easily ported from
the TDI Modula-2/1 version.
Date: 23-Mar-1987
Author: Reinhold P. Weicker (ADA version)
Translated from ADA by Joergen Thomsen. Compuserve: 71310,2206
ADA version published in
Communications of the ACM, October 1984, Vol. 27 Number 10
---------------------------------------------------------------------------
Original ADA comment:
The following program contains statements of a high-level programming
language (Ada) in a distribution considered representative:
assignments 53 %
control statements 32 %
procedure, function calls 15 %
100 statements are dynamically executed. The program is balanced with
respect to the three aspects:
- statement type
- operand type (for simple data types)
- operand access
operand global, local, parameter, or constant
The combination of these three aspects is balanced only approximately.
The program does not compute anything meaningful, but it is syntactically
and semantically correct. All variables have a value assigned to them
before they are used as a source operand.
---------------------------------------------------------------------------
This Modula-2 version very closely follows the Ada version because the
two languages are similar. A loop of 50000 executions of the benchmark
and proper timing code has been added.
Alfred Aburto, Compuserve: 76450,23 published these results for C:
------------------------------------------------------------------------
Manx Aztec C V3.30E with some variables assigned to registers.
------------------------------------------------------------------------
System CPU / FPP Clock Cache Memory Time Dhrystones/sec
(MHz) (bits) (sec )
Amiga (68000/-----) 7.16 ----- 16 46.2 1083
Turbo-Amiga (68020/-----) 7.16 Off 16 54.5 917
Turbo-Amiga (68020/-----) 7.16 On 16 43.1 1160
Turbo-Amiga (68020/-----) 14.32 Off 32 18.3 2729
Turbo-Amiga (68020/-----) 14.32 On 32 16.6 3008
------------------------------------------------------------------------
Lattice C V3.03. 'makesimple' and no register or short variables.
------------------------------------------------------------------------
Amiga (68000/-----) 7.16 ----- 16 ----- 458
Turbo-Amiga (68020/-----) 7.16 Off 16 128.7 388
Turbo-Amiga (68020/-----) 7.16 On 16 86.0 581
Turbo-Amiga (68020/-----) 14.32 Off 32 37.7 1326
Turbo-Amiga (68020/-----) 14.32 On 32 31.3 1595
------------------------------------------------------------------------
These that follow are Lattice C V3.03 with Short Variables defined.
------------------------------------------------------------------------
Amiga (68000/-----) 7.16 ----- 16 84.9 589
Turbo-Amiga (68020/-----) 7.16 off 16 101.8 491
Turbo-Amiga (68020/-----) 7.16 on 16 73.2 683
Turbo-Amiga (68020/-----) 14.32 off 32 29.7 1683
Turbo-Amiga (68020/-----) 14.32 on 32 25.0 2000
------------------------------------------------------------------------
TDI Modula-2 rel. 3.00a
------------------------------------------------------------------------
Amiga (68000/-----) 7.16 ----- 16 ----- 378 1)
Amiga (68000/-----) 7.16 ----- 16 87.4 571 2)
Amiga (68000/-----) 7.16 ----- 16 ----- 613 3)
Amiga (68000/-----) 7.16 ----- 16 ----- 1064 4)
------------------------------------------------------------------------
1) Using the released Strings.Compare procedure
2) Using a recoded Strings.Compare, still full general procedure.
This is probably the figure, that should be compared to the
results above.
3) Using the Compare30 procedure below, similar to compiler generated
inline code from many compilers
4) Using no string comparison at all
------------------------------------------------------------------------
Benchmark Modula-2 rel. 1.02
------------------------------------------------------------------------
Amiga (68000/-----) 7.16 ----- 16 79.3 630 1)
Amiga (68000/-----) 7.16 ----- 16 83.5 598 2)
Amiga (68000/-----) 7.16 ----- 16 86.8 576 3)
Amiga (68000/-----) 7.16 ----- 16 49.3 1012 4)
------------------------------------------------------------------------
1) same as note 1 for TDI
2) same as note 1, except using base relative addressing (the default), as
opposed to absolute addressing which was used for entries 1,3,4
3) same as note 3 for TDI
4) hopefully same as note 4 for TDI, but I'm not sure, as I don't quite know
what was actually done in the TDI test. All I did was comment out the
call to StringCompare and substituted it with a FALSE.
-------------------------------------------------------------------------*)
FROM Memory IMPORT AllocMem, FreeMem, MemReqSet, MemPublic;
FROM TermInOut IMPORT WriteString, WriteCard, WriteLn;
FROM LongInOut IMPORT WriteLongCard, WriteLongInt;
FROM AmigaDOS IMPORT DateStamp, DateStampRecord, TicksPerSecond;
FROM Strings IMPORT CompareString, Relation;
FROM SYSTEM IMPORT LONG, TSIZE;
CONST
LOOPS = 50000;
Ticks = TicksPerSecond; (* no of timer ticks in each second *)
NULL = NIL;
TYPE
Enumeration = (Ident1, Ident2, Ident3, Ident4, Ident5);
ZeroToThirty = [0..30]; (*Modula-2*)
OneToThirty = [1..30];
OneToFifty = [1..50];
CapitalLetter = CHAR;
String30 = ARRAY ZeroToThirty OF CHAR;
Array1Dim = ARRAY OneToFifty OF CARDINAL;
Array2Dim = ARRAY OneToFifty, OneToFifty OF CARDINAL;
RecordPointer = POINTER TO RecordType;
RecordType =
RECORD
PointerComp : RecordPointer;
CASE Discr: Enumeration OF
Ident1:
EnumComp : Enumeration;
IntComp : OneToFifty;
StringComp: String30;
| Ident2:
EnumComp2 : Enumeration;
StringComp2: String30;
ELSE
CharComp1,
CharComp2: CHAR;
END; (*CASE*)
END; (*RECORD*)
VAR
IntGlob: CARDINAL;
BoolGlob: BOOLEAN;
CharGlob1,
CharGlob2: CHAR;
ArrayGlob1: Array1Dim;
ArrayGlob2: Array2Dim;
PointerGlob,
PointerGlobNext: RecordPointer;
PROCEDURE Compare30(VAR A, B: String30): Relation;
(* The string comparison accounts for a large part of the consumed
CPU time in this test.
This procedure is what a compiler might generate as inline code
based on the knowledge of the variables being tested.
*)
VAR
i: CARDINAL;
Ai, Bi: CHAR;
BEGIN
i := 0;
LOOP
Ai := A[i]; Bi := B[i];
IF (Ai <> Bi) OR (Ai = 0C) OR (Bi = 0C) OR (i = 30) THEN EXIT; END;
INC(i);
END;
IF Ai < Bi THEN RETURN less;
ELSIF Ai = Bi THEN RETURN equal;
ELSE RETURN greater; END;
END Compare30;
PROCEDURE Func3(EnumParIn: Enumeration): BOOLEAN;
(*executed once, returns TRUE
EnumParIn = Ident3
*)
VAR
EnumLoc: Enumeration;
BEGIN
EnumLoc := EnumParIn;
IF EnumLoc = Ident3
THEN (*executed*)
RETURN TRUE;
END;
RETURN FALSE; (* MODULA-2 *)
END Func3;
PROCEDURE Proc6(EnumParIn: Enumeration; VAR EnumParOut: Enumeration);
(*executed once, EnumParIn = Ident3, ENumParOut becomes Ident2*)
BEGIN
EnumParOut := EnumParIn;
IF NOT Func3(EnumParIn)
THEN (*not executed*)
EnumParOut := Ident4;
END;
CASE EnumParIn OF
Ident1: EnumParOut := Ident1;
| Ident2: IF IntGlob > 100
THEN EnumParOut := Ident1;
ELSE EnumParOut := Ident4;
END;
| Ident3: EnumParOut := Ident2; (*executed*)
| Ident4:
| Ident5: EnumParOut := Ident3;
END;
END Proc6;
PROCEDURE Proc7(IntParIn1,
IntParIn2: OneToFifty;
VAR IntParOut: OneToFifty);
(*executed three times,
first call: IntParIn1 = 2, IntParIn2 = 3, IntParOut becomes 7
second call: IntParIn1 = 6, IntParIn2 = 10, IntParOut becomes 18
third call: IntParIn1 = 10, IntParIn2 = 5, IntParOut becomes 17
*)
VAR
IntLoc: OneToFifty;
BEGIN
IntLoc := IntParIn1 + 2;
IntParOut := IntParIn2 + IntLoc;
END Proc7;
PROCEDURE Proc8(VAR ArrayParInOut1: Array1Dim;
VAR ArrayParInOut2: Array2Dim;
IntParIn1,
IntParIn2: OneToFifty);
(*executed once,
IntParIn1 = 3, IntParIn2 = 7
*)
VAR
IntLoc: OneToFifty;
IntIndex: OneToFifty; (*MODULA-2*)
BEGIN
IntLoc := IntParIn1 + 5;
ArrayParInOut1[ IntLoc ] := IntParIn2;
ArrayParInOut1[ IntLoc + 1 ] := ArrayParInOut1[ IntLoc ];
ArrayParInOut1[ IntLoc + 30 ] := IntLoc;
FOR IntIndex := IntLoc TO IntLoc + 1 DO (*loop body executed twice*)
ArrayParInOut2[ IntLoc, IntIndex ] := IntLoc;
END;
INC(ArrayParInOut2[ IntLoc, IntLoc - 1 ]);
ArrayParInOut2[ IntLoc + 20, IntLoc ] := ArrayParInOut1[ IntLoc ];
IntGlob := 5;
END Proc8;
PROCEDURE Func1(CharParIn1, CharParIn2: CapitalLetter): Enumeration;
(*executed three times, returns Ident1 each time*
first call: CharParIn1 = 'H', CharParIn2 = 'R'
second call: CharParIn1 = 'A', CharParIn2 = 'C'
third call: CharParIn1 = 'B', CharParIn2 = 'C'
*)
VAR
CharLoc1, CharLoc2: CapitalLetter;
BEGIN
CharLoc1 := CharParIn1;
CharLoc2 := CharLoc1;
IF CharLoc2 # CharParIn2 THEN RETURN Ident1; (*executed*)
ELSE RETURN Ident2; (*not executed*)
END;
END Func1;
PROCEDURE Func2(VAR StrParIn1, StrParIn2: String30): BOOLEAN;
(*executed once, returns FALSE
StringParIn1 = "DHRYSTONE, 1'ST STRING"
StringParIn2 = "DHRYSTONE, 2'ND STRING"
*)
VAR
IntLoc: OneToThirty;
CharLoc: CapitalLetter;
BEGIN
IntLoc := 1;
WHILE IntLoc <= 1 DO (*loop body executed once*)
IF Func1(StrParIn1[ IntLoc ],
StrParIn2[ IntLoc+1 ]) = Ident1
THEN (*executed*)
CharLoc := 'A';
INC(IntLoc);
END;
END;
IF (CharLoc >= 'W') AND (CharLoc < 'Z')
THEN (*not executed*)
IntLoc := 7;
END;
IF CharLoc = 'X'
THEN (*not executed*)
RETURN TRUE;
ELSE (*executed*)
IF StringCompare(StrParIn1, StrParIn2) = greater
THEN (*not executed*)
INC(IntLoc, 7);
RETURN TRUE;
ELSE (*executed*)
RETURN FALSE;
END;
END;
END Func2;
PROCEDURE time(): LONGCARD;
VAR
DS: DateStampRecord;
BEGIN
DateStamp(DS);
RETURN LONG(DS.dsMinute * (60D * Ticks) + DS.dsTick);
END time;
PROCEDURE Proc2(VAR IntParInOut: OneToFifty);
(*executed once, InParInOut = 3, becomes 7*)
VAR
IntLoc: OneToFifty;
EnumLoc: Enumeration;
BEGIN
IntLoc := IntParInOut + 10;
LOOP (*executed once*)
IF CharGlob1 = 'A' THEN (*executed*)
DEC(IntLoc);
IntParInOut := IntLoc - IntGlob;
EnumLoc := Ident1;
END;
IF EnumLoc = Ident1 THEN EXIT; END; (*TRUE*)
END;
END Proc2;
PROCEDURE Proc3(VAR PointerParOut: RecordPointer);
(*executed once, PointerParOut becomes PointerGlob (?)*)
BEGIN
IF PointerGlob # NULL THEN (*executed*)
PointerParOut := PointerGlob^.PointerComp;
ELSE (*not executed*)
IntGlob := 100;
END;
Proc7(10, IntGlob, PointerGlob^.IntComp);
END Proc3;
PROCEDURE Proc4(); (*without parameters*)
VAR (*executed once *)
BoolLoc: BOOLEAN;
BEGIN
BoolLoc := CharGlob1 = 'A';
BoolLoc := BoolLoc OR BoolGlob;
CharGlob2 := 'B';
END Proc4;
PROCEDURE Proc5(); (*without parameters*)
BEGIN (*executed once *)
CharGlob1 := 'A';
BoolGlob := FALSE;
END Proc5;
PROCEDURE Proc1(PointerParIn: RecordPointer);
BEGIN
WITH PointerParIn^ DO
PointerComp^ := PointerGlob^;
IntComp := 5;
PointerComp^.IntComp := IntComp;
PointerComp^.PointerComp := PointerComp;
Proc3(PointerComp^.PointerComp);
(*PointerComp^.PointerComp = PointerGlob^.PointerComp =
PointerGlobNext*)
IF PointerComp^.Discr = Ident1 THEN
PointerComp^.IntComp := 6;
Proc6(EnumComp, PointerComp^.EnumComp);
PointerComp^.PointerComp := PointerGlob^.PointerComp;
Proc7(PointerComp^.IntComp, 10, PointerComp^.IntComp);
ELSE
PointerParIn^ := PointerComp^;
END;
END;
END Proc1;
PROCEDURE Proc0();
VAR
IntLoc1,
IntLoc2,
IntLoc3: OneToFifty;
CharLoc,
CharIndex: CHAR;
EnumLoc: Enumeration;
StringLoc1,
StringLoc2: String30;
starttime,
benchtime,
nulltime : LONGCARD;
i: CARDINAL;
BEGIN
(* initializations *)
PointerGlobNext := AllocMem (TSIZE (RecordType), MemReqSet{MemPublic});
(* NEW(PointerGlobNext); *)
PointerGlob := AllocMem (TSIZE (RecordType), MemReqSet{MemPublic});
(* NEW(PointerGlob); *)
WITH PointerGlob^ DO
PointerComp := PointerGlobNext;
Discr := Ident1;
EnumComp := Ident3;
IntComp := 40;
StringComp := "DHRYSTONE PROGRAM, SOME STRING";
END;
StringLoc1 := "DHRYSTONE PROGRAM, 1'ST STRING";
ArrayGlob2[8][7] := 10;
(*-------------------*)
(* get loop overhead *)
(*-------------------*)
starttime := time();
FOR i := 0 TO LOOPS DO
END;
nulltime := time() - starttime;
(*-------------*)
(* start timer *)
(*-------------*)
starttime := time();
FOR i := 0 TO LOOPS DO
Proc5();
Proc4();
(* CharGlob1 = 'A', CharGlob2 = 'B', BoolGlob = FALSE *)
IntLoc1 := 2;
IntLoc2 := 3;
StringLoc2 := "DHRYSTONE PROGRAM, 2'ND STRING";
EnumLoc := Ident2;
BoolGlob := NOT Func2(StringLoc1, StringLoc2);
(* BoolGlob = TRUE *)
WHILE IntLoc1 < IntLoc2 DO (*loop body executed once*)
IntLoc3 := 5 * IntLoc1 - IntLoc2; (*IntLoc3 = 7*)
Proc7(IntLoc1, IntLoc2, IntLoc3); (*IntLoc3 = 7*)
INC(IntLoc1);
END; (* WHILE, IntLoc1 = 3*)
Proc8(ArrayGlob1, ArrayGlob2, IntLoc1, IntLoc3); (*IntGlob = 5*)
Proc1(PointerGlob);
FOR CharIndex := 'A' TO CharGlob2 DO (*loop body executed twice*)
IF EnumLoc = Func1(CharIndex, 'C') THEN (*not executed*)
Proc6(Ident1, EnumLoc);
END;
END; (*FOR*)
(*EnumLoc = Ident1
IntLoc1 = 3, IntLoc2 = 3, IntLoc3 = 7 *)
IntLoc3 := IntLoc2 * IntLoc1;
IntLoc2 := IntLoc3 DIV IntLoc1;
IntLoc2 := 7 * (IntLoc3 - IntLoc2) - IntLoc1;
Proc2(IntLoc1);
END; (* FOR *)
(*------------*)
(* stop timer *)
(*------------*)
benchtime := time() - starttime - nulltime;
WriteString("Dhrystone time for "); WriteCard(LOOPS, 5);
WriteString(" passes = ");
nulltime := benchtime DIV LONGCARD(Ticks);
WriteLongCard(nulltime, 4); WriteString(".");
WriteLongCard((benchtime * 10D DIV LONGCARD(Ticks)) MOD 10D, 1); WriteLn;
WriteString("This machine benchmarks at ");
WriteLongCard(LONGCARD(LOOPS) * LONGCARD(Ticks) DIV benchtime, 5);
WriteString(" dhrystones/second"); WriteLn;
FreeMem (PointerGlob, TSIZE (RecordType));
FreeMem (PointerGlobNext, TSIZE (RecordType));
END Proc0;
BEGIN
Proc0();
END Dhrystone.